﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using Conexion;
using System.Net.Sockets;
using System.IO;

namespace Manager
{
    class ServerController
    {

        private const string CMD_RAM = "01";
        private const string CMD_CPU = "02";
        private const string CMD_DISCO = "03";
        private const string CMD_SERV = "04";

        private const int MAX_CANT_SERV = 5;
        private Thread[] serverThreads = new Thread[5];
        private UDPCLIENTE broadcastClient;
        private Object mutex = null;

        public ServerController() {
        }

        public void IniciarServicio(Object mutex)
        {
            this.mutex = mutex;
            Thread th = new Thread(InterrogarServidores);
            th.Start();
        }

        private void InterrogarServidores()
        {
            try
            {
                broadcastClient = new UDPCLIENTE(Manager.conf.Ip_broadcast, Manager.conf.Puerto_broadcast);

                while (true)
                {
                    Thread.Sleep(1000); // Duerme un segundo

                    Console.WriteLine("Interrogando Servidores...");
                    int count = 0;
                    foreach (ServerNode s in Manager.conf.ObtenerServidores())
                    {
                        serverThreads[count] = new Thread(EnviarComandosServidor);
                        serverThreads[count].Start(s);
                        count++;
                    }
                    if (serverThreads[0] != null) serverThreads[0].Join();
                    if (serverThreads[1] != null) serverThreads[1].Join();
                    if (serverThreads[2] != null) serverThreads[2].Join();
                    if (serverThreads[3] != null) serverThreads[3].Join();
                    if (serverThreads[4] != null) serverThreads[4].Join();

                    EnviarBroadCast();
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                Console.Read();
            }
        }

        private void EnviarComandosServidor(object objServidor)
        {
            ServerNode srv = null;
            try{
                Thread[] ths = new Thread[3];
                srv = (ServerNode)objServidor;

                ths[0] = new Thread(new RequestAgent(mutex, srv).EnviarRequestAgente);
                ths[0].Start(new Command(srv, CMD_CPU));
                ths[1] = new Thread(new RequestAgent(mutex, srv).EnviarRequestAgente);
                ths[1].Start(new Command(srv, CMD_DISCO));
                ths[2] = new Thread(new RequestAgent(mutex, srv).EnviarRequestAgente);
                ths[2].Start(new Command(srv, CMD_RAM));

                if (ths[0] != null) ths[0].Join();
                if (ths[1] != null) ths[1].Join();
                if (ths[2] != null) ths[2].Join();
            }
            catch (Exception)
            {
              //  Manager.conf.EliminarServidor(srv);
                Console.WriteLine("El servidor " + srv.Nombre + " (" + srv.Ip + ":"+srv.Puerto+") no responde");
                srv.Vivo = false;
            }
        }

        private void EnviarBroadCast()
        {
            Console.WriteLine("Enviando Broadcast a Clientes...\n");
            
            string MsjBroadcast = "BRO";

            // Cantidad de servidores
            MsjBroadcast += CMD_SERV;
            MsjBroadcast += Manager.conf.ObtenerCantServidores().ToString(); 

            // Memoria RAM
            MsjBroadcast += CMD_RAM;  
            MsjBroadcast += ObtenerRamTotal();
            MsjBroadcast += ObtenerRamLibre();

            // Uso de CPU
            MsjBroadcast += CMD_CPU;  
            MsjBroadcast += ObtenerUsoCpu();

            // Espacion en Disco
            MsjBroadcast += CMD_DISCO;  
            MsjBroadcast += ObtenerDiscoTotal();
            MsjBroadcast += ObtenerDiscoLibre();

            broadcastClient.sendTo(MsjBroadcast);
        }

        private string ObtenerRamTotal()
        {
            float sumaParcial = 0;
            foreach (ServerNode serv in Manager.conf.ObtenerServidores())
            {
                if (serv.Vivo)
                    sumaParcial += float.Parse(serv.RamTotal);
            }
            return sumaParcial.ToString("000000000000000");
        }

        private string ObtenerRamLibre()
        {
            float sumaParcial = 0;
            foreach (ServerNode serv in Manager.conf.ObtenerServidores())
            {
                if (serv.Vivo)
                    sumaParcial += float.Parse(serv.RamLibre);
            }
            return sumaParcial.ToString("000000000000000");
        }

        private string ObtenerDiscoTotal()
        {
            long sumaParcial = 0;
            foreach (ServerNode serv in Manager.conf.ObtenerServidores())
            {
                if (serv.Vivo)
                    sumaParcial += long.Parse(serv.DiscoTotal);
            }
            return sumaParcial.ToString("000000000000000");
        }

        private string ObtenerDiscoLibre()
        {
            long sumaParcial = 0;
            foreach (ServerNode serv in Manager.conf.ObtenerServidores())
            {
                if (serv.Vivo)
                    sumaParcial += long.Parse(serv.DiscoLibre);
            }
            return sumaParcial.ToString("000000000000000");
        }

        private string ObtenerUsoCpu()
        {
            long sumaParcial = 0;
            foreach (ServerNode serv in Manager.conf.ObtenerServidores())
            {
                if (serv.Vivo)
                    sumaParcial += long.Parse(serv.UsoCpu);
            }
            return sumaParcial.ToString("000000000000000");
        }

    }

}
